#include <SDL/SDL.h>
#include <iostream>
#include "string.h"
#include "Effect.h"
#include "Text.h"

using namespace std;
using namespace JDL;

Text::Text(const string str, const string font, int size)
{
  _str = str;
  _color.r = 255;
  _color.g = 255;
  _color.b = 255;
  this->InitRect(&_clipper);
  this->InitRect(&_pos);
  this->InitRect(&_old_pos);
  this->InitRect(&_pos_c);
  this->InitRect(&_zone);
  this->Init(font, size);
  this->GetLines();
  this->WriteSurface();
  _zone.w = _surface->w;
  _zone.h = _surface->h;
}

Text::~Text()
{
  TTF_CloseFont(_font);
  SDL_FreeSurface(_surface);
}

char		*Text::GetToken(const char *str, int *pos)
{
  char		*token;
  int		size;
  int		i;

  i = *pos;
  size = 0;
  while (str[i] && str[i] != '\n')
    {
      size++;
      i++;
    }
  i = 0;
  token = (char*)malloc(sizeof(char) * (size + 1));
  while (i < size)
    {
      token[i] = str[*pos];
      *pos = *pos + 1;
      i++;
    }
  token[i] = '\0';
  return (token);
}

void		Text::SetColor(int r, int g, int b)
{
  _color.r = r;
  _color.g = g;
  _color.b = b;
  SDL_FillRect(_surface, NULL, SDL_MapRGB(_surface->format, 0, 0, 0));
  this->GetLines();
  this->WriteSurface();
}

void		Text::GetLines()
{
  int		max_char;
  char		*word;
  int		size;
  const char	*c_str;
  int		i;
  list<char*>	tokens;

  i = 0;
  size = _str.size();
  c_str = _str.c_str();
  while (i < size && c_str[i])
    {
      if (c_str[i] != '\n')
	{
	  word = this->GetToken(c_str, &i);
	  tokens.push_back(word);
	  i++;
	}
      else
	i++;
    }
  _nb_line = tokens.size() + 1;
  max_char = this->GetMaxChar(tokens);
  this->CreateTextSurface(max_char);
  while (!tokens.empty())
    tokens.pop_back();
}

int	Text::GetMaxChar(list<char*> &tokens)
{
  int		tmp;
  int		max_size;
  list<char*>::iterator	it;

  max_size = 0;
  for (it = tokens.begin(); it != tokens.end(); it++)
    {
      if (max_size == 0)
	max_size = strlen(*it);
      tmp = strlen(*it);
      if (tmp > max_size)
	max_size = tmp;
      _lines.push_back(TTF_RenderText_Blended(_font, *it, _color));
    }
  _saut = _lines[0]->h;
  return (max_size);
}

void	Text::WriteSurface()
{
  SDL_Rect	pos;
  int		i;

  i = 0;
  pos.x = _pos.x;
  pos.y = _pos.y;
  while (i < (int)_lines.size())
    {
      SDL_BlitSurface(_lines[i], NULL, _surface, &pos);
      pos.y += _saut;
      i++;
    }
  this->DestroyLines();
}

void	Text::DestroyLines()
{
  while (!_lines.empty())
    _lines.pop_back();
}

void	Text::Init(const string font, int size)
{
  _font = TTF_OpenFont(font.c_str(), size);
  if (_font == NULL)
    cerr << " Error : " << SDL_GetError() << endl;
  _nb_line = 0;
  _size_font = size;
}

void	Text::CreateTextSurface(int max_char)
{
  _size.w = max_char * (_size_font + 1);
  _size.h = _nb_line * (_size_line.h + _saut);
  _surface = SDL_CreateRGBSurface(SDL_HWSURFACE, _size.w, _size.h, 32, 0, 0, 0, 0);
  SDL_FillRect(_surface, NULL, SDL_MapRGB(_surface->format, _color.r + 1, _color.g + 1, _color.b + 1));
  SDL_SetColorKey(_surface, SDL_SRCCOLORKEY, SDL_MapRGB(_surface->format, _color.r + 1, _color.g + 1, _color.b + 1));
}

void	Text::Render(SDL_Surface *screen)
{
  Effect				*eff;
  std::map<string, Effect*>::iterator	it;

  _pos_c.x = _pos.x;
  _pos_c.y = _pos.y;
  SDL_BlitSurface(_surface, &_zone, screen, &_pos_c);
  for (it = _effect.begin(); it != _effect.end(); it++)
    {
      eff = it->second;
      eff->Do(this);
    }
}
